# -*- coding: UTF-8 -*-

import json
import hashlib
import random
import time

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.hashers import make_password, check_password
from django.core import signing
from django.core.cache import cache
from django.core.mail import send_mail, BadHeaderError
from django.http import JsonResponse
from django.http import HttpResponseRedirect
from rest_framework.views import APIView

from user.models import UserProfile, UserToken
#from user.tasks import celery_send_email
from mysite.tasks import celery_send_email
from mysite import settings


HEADER = {'typ': 'JWT', 'alg': 'HS256'}
KEY = 'bouffalolab'
SALT = 'bouffalo'
SECRET = 'bouffalo2020'
TIME_OUT = 60 * 60 * 24 * 7  # 1week



def encrypt(obj):
    """加密"""
    value = signing.dumps(obj, key=KEY, salt=SALT)
    value = signing.b64_encode(value.encode()).decode()
    return value


def decrypt(src):
    """解密"""
    src = signing.b64_decode(src.encode()).decode()
    raw = signing.loads(src, key=KEY, salt=SALT)
    return raw


def create_token(username):
    """生成token信息"""
    # 1. 加密头信息
    header = encrypt(HEADER)
    # 2. 构造Payload
    payload = {"username": username, "secret": SECRET, "exp": time.time()+TIME_OUT}
    payload = encrypt(payload)
    # 3. 生成签名
    md5 = hashlib.md5()
    md5.update(("%s.%s" % (header, payload)).encode())
    signature = md5.hexdigest()
    token = "%s.%s.%s" % (header, payload, signature)
    # 存储到缓存中
    # cache.set(username, token, TIME_OUT)
    return token


def get_payload(token):
    payload = str(token).split('.')[1]
    payload = decrypt(payload)
    return payload


# 通过token获取用户名，过期时间，加密内容
def get_info(token):
    payload = get_payload(token)
    return payload['username'], payload['secret'], payload['exp']


def get_username(token):
    payload = get_payload(token)
    return payload['username']


# 校验token
def check_token(token):
    username, secret_token, exp = get_info(token)
    print(username, secret_token, exp)
    now = time.time()
    print(now)
    if float(exp) < now:
        # token expired
        return False
    if secret_token != SECRET:
        # token certification failed
        return False
    '''
    last_token = cache[username]
    if last_token & last_token == token:
        return True
    '''
    return True


# 检测状态
def check_status(request):
    ret = {'code': 401, 'msg': 'noLogin', 'user': None}
    try:
        token = request.META.get('HTTP_X_CSRFTOKEN')
        if str(token) != "undefined" and token != None:
            print("new token is " + str(token))
            res = check_token(token)
            print(res)
            if res:
                ret['code'] = 200
                ret['msg'] = "Login"
                ret['user'] = get_username(token)
        else:
            ret['msg'] = "noToken"
    except Exception as error:
        print(error)
    return JsonResponse(ret)


# 检测账户
def check_user(request):
    if request.method == 'GET':
        ret = {'code': 401, 'msg': None, 'username': None, 'name': None, 'email': None, 'phone': None, 'company': None}
        username = request.GET.get('username')
        try:
            token = request.META.get('HTTP_X_CSRFTOKEN')
            if str(token) != "undefined" and token != None:
                print("new token is " + str(token))
                res = check_token(token)
                print(res)
                if res and get_username(token) == username:
                    try:
                        obj = UserProfile.objects.get(username=username)
                        ret['code'] = 200
                        ret['username'] = username
                        ret['name'] = obj.name
                        ret['email'] = obj.email
                        ret['phone'] = obj.phone
                        ret['company'] = obj.company
                    except Exception as error:
                        print(error)
                else:
                    ret['msg'] = "用户不匹配"
            else:
                ret['msg'] = "noToken"
        except Exception as error:
            print(error)
        return JsonResponse(ret)


def register(request):
    '''
        用户注册
    ret = {'code': 100, 'msg': None}
    ret字典为自定义状态码
    100：正常
    101：用户名已存在
    102：邮箱已存在
    103：注册时获取前端提交用户名和密码错误或者是数据库读写错误
    '''
    if request.method == 'POST':
        ret = {'code': 401, 'msg': None}
        try:
            #user = request._request.POST.get('username')
            #pwd = request._request.POST.get('password')
            #gender = request._request.POST.get('gender')
            postBody = request.body
            json_result = json.loads(postBody)
            #print(json_result)
            user = json_result.get('username', "").strip()
            pwd = json_result.get('password', "").strip()
            email = json_result.get('email', "").strip()
            #gender = json_result.get('gender', "")
            #birthday = json_result.get('birthday', "")
            #phone = json_result.get('phone', "")
            #pwd_encrypt = make_password(pwd, "tanjiaxi", 'pbkdf2_sha256')
            pwd_encrypt = make_password(pwd, SALT)
            obj1 = UserProfile.objects.filter(username=user).first()
            obj2 = UserProfile.objects.filter(email=email).first()
            if obj1:
                ret['code'] = 102
                ret['msg'] = u'用户名已经存在'
            elif obj2:
                ret['code'] = 103
                ret['msg'] = u'邮箱已经存在'    
            else:
                UserProfile.objects.create(username=user, password=pwd_encrypt, email=email)
                ret['code'] = 100
                ret['msg'] = u'用户注册成功，请登录'
        except Exception as error:
            print(error)
            ret['code'] = 101
            ret['msg'] = u'注册时获取前端提交账户和密码错误或者是数据库读写错误'
        return JsonResponse(ret)


def modify(request):
    '''
        用户修改
    ret = {'code': 100, 'msg': None}
    ret字典为自定义状态码
    100：正常
    101：用户名不存在
    102：修改时获取前端提交用户名和密码错误或者是数据库读写错误
    '''
    if request.method == 'POST':
        ret = {'code': 401, 'msg': None}
        try:
            #user = request._request.POST.get('username')
            #pwd = request._request.POST.get('password')
            #gender = request._request.POST.get('gender')
            postBody = request.body
            json_result = json.loads(postBody)
            #print(json_result)
            user = json_result.get('username', "")
            token = request.META.get('HTTP_X_CSRFTOKEN')
            if str(token) != "undefined" and token != None:
                print("new token is " + str(token))
                res = check_token(token)
                print(res)
                if res and get_username(token) == user:
                    pwd = json_result.get('password', "").strip()
                    email = json_result.get('email', "").strip()
                    if json_result.get('name', "") is not None:
                        name = json_result.get('name', "").strip()
                    else:
                        name = json_result.get('name', "")
                    if json_result.get('company', "") is not None:
                        company = json_result.get('company', "").strip()
                    else:
                        company = json_result.get('company', "")
                    if json_result.get('phone', "") is not None:
                        phone = json_result.get('phone', "").strip()
                    else:
                        phone = json_result.get('phone', "")
                    #pwd_encrypt = make_password(pwd, "tanjiaxi", 'pbkdf2_sha256')
                    pwd_encrypt = make_password(pwd, SALT)
                    user1 = UserProfile.objects.filter(username__exact=user).first()
                    if user1:
                        UserProfile.objects.select_for_update().filter(username__exact=user).update(name=name, phone=phone, company=company, email=email)
                        if pwd:
                            user1.password = pwd_encrypt
                            user1.save()
                        ret['code'] = 100
                        ret['msg'] = u'用户信息修改成功'
                    else:
                        ret['code'] = 102
                        ret['msg'] = u'用户不存在'
                else:
                    ret['code'] = 103
                    ret['msg'] = "用户不匹配"
            else:
                ret['msg'] = "noToken"
        except Exception as error:
            print(error)
            ret['code'] = 101
            ret['msg'] = u'修改时获取前端提交账户和密码错误或者是数据库读写错误'
        return JsonResponse(ret)


def custom_login(request):
    '''
            用户登录
    '''
    if request.method == 'POST':
        ret = {'code': 401, 'msg': None}
        try:
            #user = request._request.POST.get('username')
            #pwd = request._request.POST.get('password')
            postBody = request.body
            json_result = json.loads(postBody)
            #print(json_result)
            user = json_result.get('username', "").strip()
            pwd = json_result.get('password', "").strip()
            if user == "admin":
                user = authenticate(username=user, password=pwd)
                if user is not None:
                    login(request, user)
                    ret['code'] = 105
                    ret['msg'] = '跳转到管理后台'
                    return JsonResponse(ret)
            #pwd_encrypt = make_password(pwd, "tanjiaxi", 'pbkdf2_sha256')
            #pwd_encrypt = make_password(pwd, SALT)
            #print(pwd_encrypt)
            user1 = UserProfile.objects.filter(username__iexact=user).first()
            user2 = UserProfile.objects.filter(email__iexact=user).first()
            if user1:
                if user1.status == True:
                    if check_password(pwd, user1.password):
                        user = user1.username
                        # 为登录用户创建token
                        #token = hashlib.md5(user.encode("utf-8")).hexdigest()
                        token = create_token(user)
                        print(token)
                        # 存在则更新，反之创建
                        #UserToken.objects.update_or_create(user=obj, defaults={'token': token})
                        ret['token'] = token
#                         user = authenticate(username=user, password=pwd)
#                         print("User is " + str(user))
#                         if user is not None:
#                             login(request, user)
                        ret['code'] = 100
                        ret['msg'] = '登录成功'
                    else:
                        ret['code'] = 102
                        ret['msg'] = '密码错误'
                else:
                    ret['code'] = 103
                    ret['msg'] = '账号被禁用'
            elif user2:
                if user2.status == True:
                    if check_password(pwd, user2.password):
                        user = user2.username
                        # 为登录用户创建token
                        #token = hashlib.md5(user.encode("utf-8")).hexdigest()
                        token = create_token(user)
                        print(token)
                        # 存在则更新，反之创建
                        #UserToken.objects.update_or_create(user=obj, defaults={'token': token})
                        ret['token'] = token
#                         user = authenticate(username=user, password=pwd)
#                         print("User is " + str(user))
#                         if user is not None:
#                             login(request, user)
                        ret['code'] = 100
                        ret['msg'] = '登录成功'
                    else:
                        ret['code'] = 102
                        ret['msg'] = '密码错误'  
                else:
                    ret['code'] = 103
                    ret['msg'] = '账号被禁用'             
            else:
                ret['code'] = 104
                ret['msg'] = '账号错误'
        except Exception as error:
            print(error)
            ret['code'] = 101
            ret['msg'] = '登录时获取前端提交用户名和密码错误或者是数据库读写错误'
        return JsonResponse(ret)


def custom_logout(request):
    '''
     用户注销
    '''
    ret = {'code': 401, 'msg': '用户未登陆'}
    if request.user.is_authenticated:
        try:
            #logout(request)
            ret = {'code': 100, 'msg': '用户注销成功'}
        except Exception as error:
            print(error)
            ret['code'] = 101
            ret['msg'] = '用户注销失败'
    return JsonResponse(ret)
  
        

def find_pwd(request):
    '''
       找回密码
    '''
    if request.method == 'POST':
        ret = {'code': 401, 'msg': None}
        try:
            #user = request._request.POST.get('username')
            #pwd = request._request.POST.get('password')
            postBody = request.body
            json_result = json.loads(postBody)
            #print(json_result)
            email = json_result.get('email', "")
            user = UserProfile.objects.filter(email__iexact=email).first()
            if user:
                username = user.username
                code_list = []
                for i in range(10):     # 0-9
                    code_list.append(str(i))
#                 for i in range(65, 91): # A-Z
#                     code_list.append(chr(i))
                for i in range(97, 123): # a-z
                    code_list.append(chr(i))
                myslice = random.sample(code_list, 6)  
                pwd = ''.join(myslice)
                pwd_encrypt = make_password(pwd, SALT)
                #UserProfile.objects.select_for_update().filter(email__iexact=email).update(password=pwd_encrypt)
                user.password = pwd_encrypt
                user.save()
                content = "用户名：" + username + "，新密码：" + pwd
                maillist = [email]
                #send_mail(u'【博流智能开发者社区】密码重置', content, settings.EMAIL_HOST_USER, maillist, fail_silently=False)                               
                celery_send_email.delay(u'【博流智能开发者社区】密码重置', content, settings.EMAIL_HOST_USER, maillist)
                ret['code'] = 100
                ret['msg'] = '新密码已发送至注册邮箱，请查收'
            else:
                ret['code'] = 102
                ret['msg'] = '账号不存在，请先注册'
        except Exception as error:
            print(error)
            ret['code'] = 101
            ret['msg'] = '重置密码失败'
        return JsonResponse(ret)
